#include "openglRenderer.h"

bool OpenGLRenderer::setup(HWND hwnd) {
	this->windowHWND = hwnd;

	if (!createContext()) {
		return false;
	}

	if (!setupRenderer()) {
		return false;
	}

	return true;
}

void OpenGLRenderer::reshapeWindow(int x, int y, int width, int height) {
	this->windowWidth = width;
	this->windowHeight = height;

	glViewport(0, 0, windowWidth, windowHeight);
}

bool OpenGLRenderer::setupRenderer() {
	glEnable(GL_DEPTH_TEST);
	glCullFace(GL_BACK);
	glClearDepth(1.0);
	glClearColor(0.3f, 0.3f, 0.3f, 1.0f);

	return true;
}

bool OpenGLRenderer::renderView() {
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	SwapBuffers(windowHDC);
	return true;
}

bool OpenGLRenderer::createContext() {
	
#ifdef _WINDOWS
	windowHDC = GetDC(windowHWND);

	PIXELFORMATDESCRIPTOR pfd;  // Create a new PIXELFORMATDESCRIPTOR (pfd)
	memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));  // Clear our PFD
	pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);  // Set the size of the PFD to the size of the class
	pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;  // Enable double buffering, opengl support and drawing to a window
	pfd.iPixelType = PFD_TYPE_RGBA;  // Set our application to use RGBA pixels
	pfd.cColorBits = 32;  // Give us 32 bits of color information (the higher, the more colors)
	pfd.cDepthBits = 32;  // Give us 32 bits of depth information (the higher, the more depth levels)
	pfd.iLayerType = PFD_MAIN_PLANE;  // Set the layer of the PFD

	int nPixelFormat = ChoosePixelFormat(windowHDC, &pfd);  // Check if our PFD is valid and get a pixel format back
	if (nPixelFormat == 0)
		return false;

	BOOL bResult = SetPixelFormat(windowHDC, nPixelFormat, &pfd);  // Try and set the pixel format based on our PFD
	if (!bResult)
		return false;

	HGLRC tempOpenGLContext = wglCreateContext(windowHDC);  // Create an OpenGL 2.1 context for our device context
	wglMakeCurrent(windowHDC, tempOpenGLContext);  // Make the OpenGL 2.1 context current and active

	GLenum error = glewInit();  // Enable GLEW
	if (error != GLEW_OK)  // if GLEW fails
		return false;

	int attributes[] = {
		WGL_CONTEXT_MAJOR_VERSION_ARB, 4,  // Set the MAJOR version of OpenGL to 3
		WGL_CONTEXT_MINOR_VERSION_ARB, 3,  // Set the MINOR version of OpenGL to 2
		WGL_CONTEXT_FLAGS_ARB,  WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
		0
	};

	if (wglewIsSupported("WGL_ARB_create_context") == 1) {  // If the OpenGL 3.x context creation extension is available
		windowHRC = wglCreateContextAttribsARB(windowHDC, NULL, attributes);  // Create an OpenGL 3.x context based on the given attributes
		wglMakeCurrent(windowHDC, NULL);  // Remove the temporary context from being active
		wglDeleteContext(tempOpenGLContext);  // Delete the temporary OpenGL 2.1 context
		wglMakeCurrent(windowHDC, windowHRC);  // Make our OpenGL 3.0 context current
	} else {
		windowHRC = tempOpenGLContext;  // If we didn't have support for OpenGL 3.x and up, use the OpenGL 2.1 context
	}

	int glVersion[2] = {2, 1};  // Set some default values for the version
	glGetIntegerv(GL_MAJOR_VERSION, &glVersion[0]);  // Get the OpenGL MAJOR version number
	glGetIntegerv(GL_MINOR_VERSION, &glVersion[1]);  // Get the OpenGL MINOR version number

	const char* version = (const char*)glGetString(GL_VERSION);

	//char s[256];
	//sprintf_s(s, ("[OpenglVersion]: %s\n"), version);
	//OutputDebugStringA(s);

	return true;  // We have successfully created a context
#endif

	return false;
}